﻿using UnityEngine;
using XMLData.Map;
using XMLReaderWriter;
using System.Collections.Generic;
using System.Xml;

public class LevelManager : MonoBehaviour {
	
	static LevelManager instance;
	
	//Map setup variables
	public string MapName;

	//Current map available option
	public List<string> MapList;
	MapInfo MapInfo;
	MapInfoXML MIXML;
	//
	public GameObject LeverDoorPrefab;
	public GameObject LeverPrefab;
	public GameObject SpikePrefab;
	public GameObject MovingPlatform;
	public GameObject GroundButton;
	public GameObject KeyPrefab;
	public GameObject KeyDoorPrefab;
	public GameObject PushBoxPrefab;
	public GameObject LadderPrefab;
	public GameObject RopePrefab;
	public GameObject ChomperPrefab;
	public GameObject HiddenPlatform;
	public GameObject HiddenPlatformBTN;
	public GameObject MultilockDoorButton;
	public GameObject MultiLockDoor;
	public GameObject CheckPoint;
	public GameObject Goal;
	public GameObject Tutorial;
	public GameObject SpawnPoint;
	
	void Awake()
	{
		instance = this;
	}
	
	void Start () 
	{
		MapList = new List<string>();
		//this.GetComponent<LevelBuilderGUI>().enabled = true;
	}
	
	public void LoadMap()
	{
		MIXML = new MapInfoXML(MapName);
		MapInfo = MIXML.LoadXML() as MapInfo;
		LevelGrid.Instance.loadCellGrid(MapInfo, true);
		LevelColliderMaker.Instance.Load(MapInfo.clusterList, true);
		LevelGrid.Instance.LoadBGPackage(MapInfo);
		LevelGrid.Instance.LoadAllObjects(MapInfo, true);
		LevelGrid.Instance.ActivateWorld(1);
	}
	
	public void SelecteMap()
	{
		Debug.Log("ENTER SELECTEMAP" + MapName); 
		MIXML = new MapInfoXML(MapName);
		MapInfo = MIXML.LoadXML() as MapInfo;
	}
	
	public void SetMap()
	{
		MapName = GameObject.FindGameObjectWithTag("DataManager").GetComponent<DataScript>().loadedLevel + ".xml";
	}
	
	public void DeleteMap()
	{
		LevelGrid.Instance.destroyGrid();
		MIXML.Delete();
	}
	
	public void WrapMap(string nextMap)
	{
		GameObject[,] _world1 = LevelGrid.Instance.World1;
		GameObject[,] _world2 = LevelGrid.Instance.World2;
		
		int xLength = (int)LevelGrid.Instance.gridSize.X;
		int yLength = (int)LevelGrid.Instance.gridSize.Y;
		
		ICell[] world1Arr = new ICell[xLength * yLength];
		ICell[] world2Arr = new ICell[xLength * yLength];
		
		//Create a List of All CellGrid
		int count = 0;
		for(int y = 0; y < yLength; y++)
		{
			for(int x = 0; x < xLength; x++)
			{
				ICell ci1 = WrapGameObject(_world1[x,y],x,y);
				ICell ci2 = WrapGameObject(_world2[x,y],x,y);
				
				world1Arr[count] = ci1;
				world2Arr[count] = ci2;
				
				count++;
			}
		}
		
		//Instantiate an XML Serialized class
		MapInfo  = new MapInfo();
		
		//Store cell information of both worlds on serialized class
		MapInfo.world1 = world1Arr.Clone() as ICell[];
		MapInfo.world2 = world2Arr.Clone() as ICell[];
		
		//Store cell colliders of both world
		MapInfo.clusterList = LevelColliderMaker.Instance.Package();
		
		//Store Grid Length
		GridSize length = LevelGrid.Instance.gridSize;
		MapInfo.lengthX = (int)length.X;
		MapInfo.lengthY = (int)length.Y;
		
		//Store BG and Objects of World 1
		MapInfo.bg1 = LevelGrid.Instance.BG1Theme;
		MapInfo.tileObj1 = LevelGrid.Instance.PackageObjectOfWorld(1);
		
		//Store BG and Objects of World 2
		MapInfo.tileObj2 = LevelGrid.Instance.PackageObjectOfWorld(2);
		
		//Create an XML Serializer with map name
		if(MapName.Contains(".xml"))
		{
			MIXML = new MapInfoXML(MapName);
			DataScript.RecentMapExport(MapName);
		}
		else
		{
			MapName = MapName.Insert(MapName.Length, ".xml");
			MIXML = new MapInfoXML(MapName);
			DataScript.RecentMapExport(MapName);
		}
		
		if(nextMap.Contains(".xml"))
		{
			MapInfo.nextMap = nextMap;
		}
		
		else
		{
			MapInfo.nextMap = nextMap.Insert(nextMap.Length, ".xml");
		}
		
		
		//Create an XML of map type
		MIXML.CreateXML(MapInfo);
	}
	

	ICell WrapGameObject(GameObject go, int gridX, int gridY)
	{
		CellGrid cg = go.GetComponent<CellGrid>();
		
		if(cg == null)
		{
			throw new System.NullReferenceException("GameObject: " + go.name + " must have Cell Grid");
		}
		
		Vector3 position = go.transform.position;
			
		ICell ci = new XMLData.Map.ICell();
		
		//Assign the position of the Cell
		ci.x = position.x;
		ci.y = position.y;
		ci.z = position.z;
		
		ci.iSee = go.GetComponent<CellGrid>().HasTexture;
		ci.n = go.name;
		
		ci.gX = gridX;
		ci.gY = gridY;
		
		return ci;
	}
	
	public void Play()
	{
		LevelGrid.Instance.destroyGrid();
		MIXML = new MapInfoXML(MapName);
		MapInfo = MIXML.LoadXML() as MapInfo;
		LevelGrid.Instance.mapInfo = MapInfo;
		LevelGrid.Instance.loadCellGrid(MapInfo, false);
		LevelColliderMaker.Instance.Load(MapInfo.clusterList, false);
		LevelGrid.Instance.LoadBGPackage(MapInfo);
		LevelGrid.Instance.LoadAllObjects(MapInfo, false);
	}
	
	public void Play(int world)
	{
		LevelGrid.Instance.destroyGrid();
		MIXML = new MapInfoXML(MapName);
		MapInfo = MIXML.LoadXML() as MapInfo;
		LevelGrid.Instance.mapInfo = MapInfo;
		LevelGrid.Instance.loadCellGrid(MapInfo, false);
		LevelColliderMaker.Instance.Load(MapInfo.clusterList, false);
		LevelGrid.Instance.LoadBGPackage(MapInfo);
		LevelGrid.Instance.LoadAllObjects(MapInfo, false, world);
	}
	
	static public bool isMapWritable(string mapName)
	{
		//Create an XML Serializer with map name
		if(!mapName.Contains(".xml"))
		{
			mapName = mapName.Insert(mapName.Length, ".xml");
		}
		
		//Set the ignore list
		for(int i = 0; i < 7; i++)
		{
			string levelName = "Level" + (i + 1).ToString() + ".xml";
			if(levelName == mapName)
				return false;
		}
		Debug.Log(mapName + " is writtable");
		return true;
	}
	
	public static LevelManager Instance
	{
		get {return instance;}
	}
}
